package com.simp.utils;

import com.simp.expection.GlobalException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.stereotype.Component;

import java.nio.charset.Charset;

/**
 * @author pan.shun
 * @since 2022/3/16 11:35
 */
@Component
public class SpringContextUtils implements ApplicationContextAware {
    private static final Logger log = LoggerFactory.getLogger(SpringContextUtils.class);
    private static ApplicationContext applicationContext;

    public SpringContextUtils() {
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (applicationContext == null) {
            log.info("初始化:{},通过该工具类可以实现获取其他组件", this.getClass().getSimpleName());
            applicationContext = applicationContext;
        } else {
            SpringContextUtils.applicationContext = applicationContext;
        }
    }

    public static Object getBean(String name) {
        try {
            return applicationContext.getBean(name);
        } catch (Exception var2) {
            log.error(ExceptionUtils.getStackTrace(var2));
            return null;
        }
    }

    public static <T> T getBean(String name, Class<T> requiredType) {
        try {
            return applicationContext.getBean(name, requiredType);
        } catch (Exception var3) {
            log.error(ExceptionUtils.getStackTrace(var3));
            return null;
        }
    }

    public static <T> T getBean(Class<T> requiredType) {
        try {
            return applicationContext.getBean(requiredType);
        } catch (Exception var2) {
            log.error(ExceptionUtils.getStackTrace(var2));
            return null;
        }
    }

    public static boolean containsBean(String name) {
        try {
            return applicationContext.containsBean(name);
        } catch (Exception var2) {
            log.error(ExceptionUtils.getStackTrace(var2));
            return false;
        }
    }

    public static boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }

    public static Class<? extends Object> getType(String name) {
        return applicationContext.getType(name);
    }

    public static void removeBeanDefinition(String beanName) {
        AutowireCapableBeanFactory autowireCapableBeanFactory = applicationContext.getAutowireCapableBeanFactory();
        if (autowireCapableBeanFactory != null) {
            DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) autowireCapableBeanFactory;
            defaultListableBeanFactory.removeBeanDefinition(beanName);
        }

    }

    public static boolean registBean(String beanName, String beanXmlDef) {
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><beans xmlns=\"http://www.springframework.org/schema/beans\"       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd       \">";
        if (StringUtils.isEmpty(beanXmlDef)) {
            throw new GlobalException("Bean的定义不能为空");
        } else {
            xml = xml + beanXmlDef;
            xml = xml + "</beans>";
            XmlBeanFactory factory = new XmlBeanFactory(new ByteArrayResource(xml.getBytes(Charset.forName("UTF-8"))));

            try {
                if (containsBean(beanName)) {
                    beanFactory.removeBeanDefinition(beanName);
                }
            } catch (NoSuchBeanDefinitionException var9) {
                log.error(ExceptionUtils.getStackTrace(var9));
            }

            try {
                beanFactory.registerBeanDefinition(beanName, factory.getMergedBeanDefinition(beanName));
                Object obj = applicationContext.getBean(beanName);
                log.info("注册bean:{},{}", beanName, obj == null ? "失败" : "成功");
                return true;
            } catch (Exception var8) {
                log.error("注册bean:{}失败：", beanName);

                try {
                    beanFactory.removeBeanDefinition(beanName);
                } catch (Exception var7) {
                    log.error(ExceptionUtils.getStackTrace(var7));
                }

                log.error(ExceptionUtils.getStackTrace(var8));
                return false;
            }
        }
    }
}